/**
 * @file   type_traits_detail.hpp
 * @author wolfhead <wolfhead@wolfhead-laptop>
 * @date   Tue Sep  6 16:48:15 2011
 * 
 * @brief  
 * 
 * 
 */
#ifndef ACAPELLA_TRAITS_TYPE_TRAITS_DETAIL_HPP
#define ACAPELLA_TRAITS_TYPE_TRAITS_DETAIL_HPP

namespace acapella
{
namespace traits
{
namespace __detail__
{

/**
 * IsPointerType determine whether the type is a pointer
 * 
 */
template <typename T>
struct IsPointerTraits
{
    enum {result = false};
};

template <typename T>
struct IsPointerTraits<T *>
{
    enum {result = true};
};

/**
 * IsMemberPointerTraits determine whether the type is a member pointer
 */
template <typename T>
struct IsMemberPointerTraits
{
    enum {result = false};
};

template <typename U, typename T>
struct IsMemberPointerTraits<U T::*>
{
    enum {result = true};
};



/**
 * IsReferenceTraits determine whether a type is reference type
 */
template <typename T>
struct IsReferenceTraits
{
    enum {result = false};
};

template <typename T>
struct IsReferenceTraits<T &>
{
    enum {result = true};
};

/**
 * IsConstTraits determine whether a type is const qualified
 */
template <typename T>
struct IsConstTraits
{
    enum {result = false};
};

template <typename T>
struct IsConstTraits<const T>
{
    enum {result = true};
};


/**
 * IsVolatileTraits determine whether a type is volatile qualified
 */
template <typename T>
struct IsVolatileTraits
{
    enum {result = false};
};

template <typename T>
struct IsVolatileTraits<volatile T>
{
    enum {result = true};
};

/**
 * IsStdUnsignedIntTraits determine whether a type is unsigned interger type
 */
template <typename T> struct IsStdUnsignedIntTraits{enum {result = false};};
template <> struct IsStdUnsignedIntTraits<unsigned char> {enum {result = true};};
template <> struct IsStdUnsignedIntTraits<unsigned short int> {enum {result = true};};
template <> struct IsStdUnsignedIntTraits<unsigned int> {enum {result = true};};
template <> struct IsStdUnsignedIntTraits<unsigned long int> {enum {result = true};};


/**
 * IsStdSignedIntTraits determine whether a type is unsigned interger type
 */
template <typename T> struct IsStdSignedIntTraits{enum {result = false};};
template <> struct IsStdSignedIntTraits<char> {enum {result = true};};
template <> struct IsStdSignedIntTraits<short int> {enum {result = true};};
template <> struct IsStdSignedIntTraits<int> {enum {result = true};};
template <> struct IsStdSignedIntTraits<long int> {enum {result = true};};

/**
 * IsStdVoidTraits determine whether a type is void
 */
template <typename T> struct IsStdVoidTraits{enum {result = false};};
template <> struct IsStdVoidTraits<void>{enum {result= true};};
template <> struct IsStdVoidTraits<const void>{enum {result= true};};

/**
 * IsStdFloatTraits determine whether a type is std float
 */
template <typename T> struct IsStdFloatTraits{enum {result = false};}; 
template <> struct IsStdFloatTraits<float>{enum {result = true};};
template <> struct IsStdFloatTraits<double>{enum {result = true};};
template <> struct IsStdFloatTraits<long double>{enum {result = true};};



/**
 * get the pointee type of a pointer
 */

template <typename T>
struct PointeeTypeTraits
{
    typedef T type;
};

template <typename T>
struct PointeeTypeTraits<T *>
{
    typedef T type;
};


/**
 * ReferencedTraits get the referenced type of a reference
 * if the type is not a reference type, then then referenced type is itself
 */
template <typename T>
struct ReferencedTypeTraits
{
    typedef T type;
};

template <typename T>
struct ReferencedTypeTraits<T &>
{
    typedef T type;
};

/**
 * NonConstTypeTraits remove the const qualifier of a type
 */
template <typename T>
struct NonConstTypeTraits
{
    typedef T type;
};

template <typename T>
struct NonConstTypeTraits<const T>
{
    typedef T type;
};


/**
 * NonVolatileTypeTraits remove the const qualifier of a type
 */
template <typename T>
struct NonVolatileTypeTraits
{
    typedef T type;
};

template <typename T>
struct NonVolatileTypeTraits<volatile T>
{
    typedef T type;
};




}//namespace __detail__
}//namespace traits
}//namespace acapella



#endif
